package com.bright.hxj.cwduijie.service;

import com.bright.hxj.cwduijie.enums.DataApi;
import com.bright.hxj.cwduijie.enums.OpType;
import com.bright.hxj.cwduijie.enums.SJJHBZ;
import com.bright.hxj.cwduijie.pojo.bo.ApiDataCollection;
import com.bright.hxj.cwduijie.pojo.dto.CheckResultDto;
import com.bright.hxj.cwduijie.pojo.query.DuijieQuery;
import com.bright.ghj.common.util.ListUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Component;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author hxj
 * @Date 2024/7/29 13:02
 * @Description 每一千条一批的对接类型
 */

@Component
@Slf4j
public abstract class AbstractPerThousandApiService<T> extends AbstractApiParentService<T> {


    public abstract Function<T, String> getDataKeyFunc();
    public abstract Function<ApiDataCollection, List<T>> getDataFunc();

    protected List<T> getNeedDuijieData(DuijieQuery duijieQuery) {
        JpaSpecificationExecutor<T> repo = getJpaSpecificationExecutor();
        String ztValue = isExistsTYSHXYDMField() ? duijieQuery.getCreditCode() : duijieQuery.getZtDataKey();
        List<T> data = repo.findAll(getDataQuerySpecification(OpType.ADD_OR_EDIT.getValue(), ztValue));
        // 加上opType为空的
        data.addAll(repo.findAll(getDataQuerySpecification(null, ztValue)));
        return data;
    }

    protected void checkDataValid(Map<String, CheckResultDto> checkResultDtoMap, ApiDataCollection apiDataCollection) {
        checkService.checkDataBeforeSend(checkResultDtoMap, getDataFunc().apply(apiDataCollection), getDataApi(), getIdFunc());
    }

    @Override
    public void sendData(ApiDataCollection apiDataCollection, DuijieQuery duijieQuery, String batchId) throws JsonProcessingException {
        List<T> dataList = getDataFunc().apply(apiDataCollection);
        sendDataPerBatchSize(dataList, getIdFunc(), batchId, duijieQuery.getAccSet(), duijieQuery.getBatchSize());
        saveSendDataKeys(dataList, getDataKeyFunc());
    }



    // 1000条推一次的类型
//    protected <PO> void sendDataPerThousand(List<PO> objs, Function<PO, Integer> getIdFunc, String batchId, Integer accSet) throws JsonProcessingException {
//        sendDataPerBatchSize(objs, getIdFunc, batchId, accSet, 1000);
//    }

    // v1.7.2 一批最多推batchSize条数据
    protected <PO> void sendDataPerBatchSize(List<PO> objs, Function<PO, Integer> getIdFunc, String batchId, Integer accSet, int batchSize) throws JsonProcessingException {
        int count = 0;
        if (objs.size() == 0) {
            // 没数据的情况
            sendListData(objs, ListUtil.toSingleList(objs, getIdFunc), batchId, accSet);
        }
        while (count < objs.size()) {
            List<PO> subObjs = ListUtil.getSubList(objs, count, count+batchSize);
            sendListData(subObjs, ListUtil.toSingleList(subObjs, getIdFunc), batchId, accSet);
            count += batchSize;
        }
    }

//    protected abstract List<T> getNeedDeleteData(DuijieQuery duijieQuery);
//    v1.6.2 把各个子类获取删除数据的方法抽到这里
    protected List<T> getNeedDeleteData(DuijieQuery duijieQuery) {
        JpaSpecificationExecutor repo = getJpaSpecificationExecutor();
        return repo.findAll(getDataQuerySpecification(OpType.DEL.getValue(),
                isExistsTYSHXYDMField() ? duijieQuery.getCreditCode() : duijieQuery.getZtDataKey()));
    }

    @Override
    public void sendDeleteData(DuijieQuery duijieQuery, String batchId) throws JsonProcessingException {
        if (getDeleteDataApi() != null) {
            sendNeedDeleteData(batchId, getNeedDeleteData(duijieQuery), getDeleteDataApi(), getDataKeyFunc(), getIdFunc(),
                    duijieQuery.getAccSet());
        }
    }



//    @Override
//    public void sendDeleteData(List<T> needDeleteData, DuijieQuery duijieQuery, String batchId, WebExchangeService webExchangeService) throws JsonProcessingException {
//        if (getDeleteDataApi() != null) {
//            sendNeedDeleteData(batchId, needDeleteData, getDeleteDataApi(), getDataKeyFunc(), getIdFunc(), duijieQuery.getAccSet());
//        }
//    }

    /**
     * 获取查询条件
     * @param opTypeValue
     * @param creditCode
     * @return
     */
    protected Specification<T> getDataQuerySpecification(Integer opTypeValue, String creditCode) {
        return (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> ps = new ArrayList<>();

            // v1.6.1 获取是使用哪个字段作为账套条件
            String ztFieldName = isExistsTYSHXYDMField() ? "TYSHXYDM" : "ZT_DATA_KEY";

            ps.add(criteriaBuilder.equal(root.get(ztFieldName), creditCode));
            ps.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("sjjhbz"), SJJHBZ.WAITING.getValue()),
                    criteriaBuilder.equal(root.get("sjjhbz"), SJJHBZ.ERROR.getValue())));
            if (opTypeValue == null) {
                ps.add(criteriaBuilder.isNull(root.get("opType")));
            } else {
                ps.add(criteriaBuilder.equal(root.get("opType"), opTypeValue));
            }

            criteriaQuery.where(ps.toArray(new Predicate[0]));
//            criteriaQuery.orderBy(criteriaBuilder.asc(root.get("id")));
            return criteriaQuery.getRestriction();
        };
    }


    @Override
    public List<Integer> getDataIds(ApiDataCollection apiDataCollection) {
        List<T> dataList = getDataFunc().apply(apiDataCollection);
        return ListUtil.toSingleList(dataList, getIdFunc());
    }
}
